package com.ruoyi.datastatistics.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.alarmmanagement.domain.DmWarn;
import com.ruoyi.alarmmanagement.mapper.DmWarnMapper;
import com.ruoyi.basedata.domain.*;
import com.ruoyi.basedata.mapper.*;
import com.ruoyi.datastatistics.domain.Realtimegatherdata;
import com.ruoyi.datastatistics.domain.TerminalsDayfreezeDb;
import com.ruoyi.datastatistics.domain.TerminalsFreezeXb;
import com.ruoyi.datastatistics.domain.TerminalsMonfreezeDb;
import com.ruoyi.datastatistics.mapper.*;
import com.ruoyi.datastatistics.service.IDashBoardService;
import com.ruoyi.datastatistics.service.IDeGaocallBackService;
import com.ruoyi.datastatistics.service.IMeterHistoryDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DashBoardServiceImpl implements IDashBoardService {
    @Autowired
    private TerminalsXbTjViewMapper terminalsXbTjViewMapper;

    @Autowired
    private TerminalsXbMapper terminalsXbMapper;

    @Autowired
    private TerminalsDbMapper terminalsDbMapper;

    @Autowired
    private RealtimegatherdataMapper realtimegatherdataMapper;

    @Autowired
    private RealtimegatherdataXbViewMapper realtimegatherdataXbViewMapper;

    @Autowired
    private ConcentratorMapper concentratorMapper;

    @Autowired
    private TerminalTypeMapper terminalTypeMapper;

    @Autowired
    private TerminalsFreezeXbMapper terminalsFreezeXbMapper;

    @Autowired
    private TerminalsDayfreezeDbMapper terminalsDayfreezeDbMapper;

    @Autowired
    private TerminalsMonfreezeDbMapper terminalsMonfreezeDbMapper;

    @Autowired
    private DmWarnMapper warnMapper;

    @Autowired
    private TerminalsFreezeXbViewMapper terminalsFreezeXbViewMapper;

    // 设备类型-大表
    private Integer DB_TYPE = 1;
    // 设备类型-小表
    private Integer XB_TYPE = 2;
    // 报警类型-大表数据中断
    private Integer WARN_TYPE_DB_MISS = 0;
    // 报警类型-大表数据不完整
    private Integer WARN_TYPE_DB_COMPLETION = 1;
    // 报警类型-大表压力数值突变
    private Integer WARN_TYPE_DB_PRESSURE = 2;
    // 报警类型-大表瞬时流量数值突变
    private Integer WARN_TYPE_DB_INSTANT_FLOW = 3;
    // 报警类型-小表持续零用量
    private Integer WARN_TYPE_XB_ZERO = 4;
    // 报警类型-小表持续未上报
    private Integer WARN_TYPE_XB_UPLOAD = 5;
    // 报警类型-小表用量突增
    private Integer WARN_TYPE_XB_FLOW = 6;

    @Override
    public Map<String, Object> getData(String tenantId) {
        Map<String, Object> resultMap = new HashMap<>();

        LocalDate now = LocalDate.now();
        String yesterday = now.minusDays(1L).toString(), lastMonth = now.minusMonths(1L).format(DateTimeFormatter.ofPattern(DatePattern.NORM_MONTH_FORMAT.getPattern()));

        // 小表数量
        List<TerminalsXb> terminalsXbList = terminalsXbMapper.selectList(new QueryWrapper<TerminalsXb>().eq("tenant_id", tenantId).eq("del_flag", 0));
        resultMap.put("numberCountXb", terminalsXbList.size());

        // 大表数量
        List<TerminalsDb> terminalsDbList = terminalsDbMapper.selectList(new QueryWrapper<TerminalsDb>().eq("tenant_id", tenantId).eq("del_flag", 0));
        resultMap.put("numberCountDb", terminalsDbList.size());

        // 大表档案数据和实时数据
        List<Realtimegatherdata> realtimegatherdataList = realtimegatherdataMapper.getRealtimegatherdataList(null, null,null,null,null,null,null,null,null);
        if (CollUtil.isNotEmpty(realtimegatherdataList)) {
            realtimegatherdataList.removeIf(item -> terminalsDbList.stream().noneMatch(terminalsDb -> terminalsDb.getTerminalId().equals(item.getTerminalId())));
        }
        resultMap.put("archiveTerminalData", terminalsDbList);
        resultMap.put("realtimeTerminalData", realtimegatherdataList);

        // 区域档案数据和实时数据
        List<TerminalsXbTjView> meterSheetsDataList = terminalsXbTjViewMapper.selectList(new QueryWrapper<TerminalsXbTjView>().eq("tenant_id", tenantId));
        resultMap.put("archiveMeterSheetsData", meterSheetsDataList);

        // 集中器数量
        //        List<Concentrator> concentratorList = concentratorMapper.selectList(new QueryWrapper<Concentrator>().eq("tenant_id", tenantId));
        resultMap.put("numberCountConcentrator", 0);

        Double healthyCountXb = 0D, healthyCountDb = 0D, healthyCountConcentrator = 0D;
        // 小表设备健康指数
        List<RealtimegatherdataXbView> realtimegatherdataXbViewList = realtimegatherdataXbViewMapper.selectList(new QueryWrapper<RealtimegatherdataXbView>().eq("tenant_id", tenantId)
                .like("read_date", now.toString()));
        if (CollUtil.isNotEmpty(terminalsXbList) && CollUtil.isNotEmpty(realtimegatherdataXbViewList)) {
            healthyCountXb = NumberUtil.round(realtimegatherdataXbViewList.size() * 1.0D / terminalsXbList.size() * 100.0, 2).doubleValue();
        }
        resultMap.put("healthyCountXb", healthyCountXb);

        // 大表设备健康指数
        List<Realtimegatherdata> healthRealtimegatherdataList = realtimegatherdataMapper.selectList(new QueryWrapper<Realtimegatherdata>().eq("tenant_id", tenantId)
                .like("read_date", now.toString()));
        if (CollUtil.isNotEmpty(terminalsDbList) && CollUtil.isNotEmpty(healthRealtimegatherdataList)) {
            healthyCountDb = NumberUtil.round(healthRealtimegatherdataList.size() * 1.0D / terminalsDbList.size() * 100.0, 2).doubleValue();
        }
        resultMap.put("healthyCountDb", healthyCountDb);

        // 集中器设备健康指数
        resultMap.put("healthyCountConcentrator", healthyCountConcentrator);

        List<TerminalType> terminalTypeList = terminalTypeMapper.selectList(new QueryWrapper<>());
        Map<Integer, List<TerminalType>> terminalTypeMap = terminalTypeList.stream().collect(Collectors.groupingBy(TerminalType::getTerminalClassify));

        // 小表类型占比
        Map<String, Object> terminalTypeXbDataMap = new HashMap<>(), terminalTypeDbDataMap = new HashMap<>();
        for (TerminalType terminalType : terminalTypeMap.get(XB_TYPE)) {
            long count = terminalsXbList.stream().filter(item -> item.getTypeId().equals(terminalType.getId().toString())).count();
            if (count > 0) {
                terminalTypeXbDataMap.put(terminalType.getTypeName(), count);
            }
        }
        resultMap.put("occupationXbTypeMap", terminalTypeXbDataMap);

        // 大表类型占比
        for (TerminalType terminalType : terminalTypeMap.get(DB_TYPE)) {
            long count = terminalsDbList.stream().filter(item -> item.getTypeId().equals(terminalType.getId().toString())).count();
            if (count > 0) {
                terminalTypeDbDataMap.put(terminalType.getTypeName(), count);
            }
        }
        resultMap.put("occupationDbTypeMap", terminalTypeDbDataMap);

        double xbDailyFlow = 0D, xbMonthlyFlow = 0D, dbDailyFlow = 0D, dbMonthlyFlow = 0D;
        // 小表日用量
        List<TerminalsFreezeXb> terminalsFreezeXbYesterdayList = terminalsFreezeXbMapper.selectList(new QueryWrapper<TerminalsFreezeXb>().eq("tenant_id", tenantId)
                .eq("frozen_type", "day").eq("freeze_time", yesterday));
        if (CollUtil.isNotEmpty(terminalsFreezeXbYesterdayList)) {
            double value = terminalsFreezeXbYesterdayList.stream().map(TerminalsFreezeXb::getCumulativeFlow).mapToDouble(item -> item == null ? 0D : item.doubleValue()).sum();
            xbDailyFlow = NumberUtil.round(value, 2).doubleValue();
        }

        // 小表月用量
        List<TerminalsFreezeXb> terminalsFreezeXbMonthList = terminalsFreezeXbMapper.selectList(new QueryWrapper<TerminalsFreezeXb>().eq("tenant_id", tenantId)
                .eq("frozen_type", "month").eq("freeze_time", lastMonth));
        if (CollUtil.isNotEmpty(terminalsFreezeXbMonthList)) {
            double value = terminalsFreezeXbMonthList.stream().map(TerminalsFreezeXb::getCumulativeFlow).mapToDouble(item -> item == null ? 0D : item.doubleValue()).sum();
            xbMonthlyFlow = NumberUtil.round(value, 2).doubleValue();
        }

        // 大表日用量
        List<TerminalsDayfreezeDb> terminalsDayfreezeDbList = terminalsDayfreezeDbMapper.selectList(new QueryWrapper<TerminalsDayfreezeDb>().eq("tenant_id", tenantId)
                .eq("get_time_n", yesterday));
        if (CollUtil.isNotEmpty(terminalsDayfreezeDbList)) {
            double value = terminalsDayfreezeDbList.stream().map(TerminalsDayfreezeDb::getDosageN).mapToDouble(item -> item == null ? 0D : item.doubleValue()).sum();
            dbDailyFlow = NumberUtil.round(value, 2).doubleValue();
        }

        // 大表月用量
        List<TerminalsMonfreezeDb> terminalsMonfreezeDbList = terminalsMonfreezeDbMapper.selectList(new QueryWrapper<TerminalsMonfreezeDb>().eq("tenant_id", tenantId)
                .eq("freeze_time", lastMonth));
        if (CollUtil.isNotEmpty(terminalsMonfreezeDbList)) {
            double value = terminalsMonfreezeDbList.stream().map(TerminalsMonfreezeDb::getDosageN).mapToDouble(item -> item == null ? 0D : item.doubleValue()).sum();
            dbMonthlyFlow = NumberUtil.round(value, 2).doubleValue();
        }

        resultMap.put("usageXbDailyFlow", xbDailyFlow);
        resultMap.put("usageXbMonthlyFlow", xbMonthlyFlow);
        resultMap.put("usageDbDailyFlow", dbDailyFlow);
        resultMap.put("usageDbMonthlyFlow", dbMonthlyFlow);

        Integer dbMissCount = 0, dbCompletionCount = 0, dbPressureCount = 0, dbInstantFlowCount = 0, xbZeroCount = 0, xbUploadCount = 0, xbFlowCount = 0;

        // 大表报警数据-数据中断、数据完整性
        List<DmWarn> dbCommWarnDataList = warnMapper.selectList(new QueryWrapper<DmWarn>().eq("tenant_id", tenantId).eq("target_type", DB_TYPE)
                .like("start_time", yesterday).and(dmWarnQueryWrapper -> dmWarnQueryWrapper.or().eq("warn_param_type", WARN_TYPE_DB_MISS)
                        .or().eq("warn_param_type", WARN_TYPE_DB_COMPLETION)));
        dbMissCount = this.getWarnCount(dbCommWarnDataList, WARN_TYPE_DB_MISS);
        dbCompletionCount = this.getWarnCount(dbCommWarnDataList, WARN_TYPE_DB_COMPLETION);

        // 大表报警数据-压力突变、瞬时流量突变
        List<DmWarn> dbInstantWarnDataList = warnMapper.selectList(new QueryWrapper<DmWarn>().eq("tenant_id", tenantId).eq("target_type", DB_TYPE)
                .like("start_time", now.toString()).and(dmWarnQueryWrapper -> dmWarnQueryWrapper.or().eq("warn_param_type", WARN_TYPE_DB_PRESSURE)
                        .or().eq("warn_param_type", WARN_TYPE_DB_INSTANT_FLOW)));
        dbPressureCount = this.getWarnCount(dbInstantWarnDataList, WARN_TYPE_DB_PRESSURE);
        dbInstantFlowCount = this.getWarnCount(dbInstantWarnDataList, WARN_TYPE_DB_INSTANT_FLOW);

        // 小表报警数据-持续零用量、持续未上报、用量突增
        List<DmWarn> xbInstantWarnDataList = warnMapper.selectList(new QueryWrapper<DmWarn>().eq("tenant_id", tenantId).eq("target_type", XB_TYPE)
                .like("start_time", yesterday).and(dmWarnQueryWrapper -> dmWarnQueryWrapper.or().eq("warn_param_type", WARN_TYPE_XB_ZERO)
                        .or().eq("warn_param_type", WARN_TYPE_XB_UPLOAD).or().eq("warn_param_type", WARN_TYPE_XB_FLOW)));
        xbZeroCount = this.getWarnCount(xbInstantWarnDataList, WARN_TYPE_XB_ZERO);
        xbUploadCount = this.getWarnCount(xbInstantWarnDataList, WARN_TYPE_XB_UPLOAD);
        xbFlowCount = this.getWarnCount(xbInstantWarnDataList, WARN_TYPE_XB_FLOW);

        resultMap.put("warnDbMissCount", dbMissCount);
        resultMap.put("warnDbCompletionCount", dbCompletionCount);
        resultMap.put("warnDbPressureCount", dbPressureCount);
        resultMap.put("warnDbInstantFlowCount", dbInstantFlowCount);
        resultMap.put("warnXbZeroCount", xbZeroCount);
        resultMap.put("warnXbUploadCount", xbUploadCount);
        resultMap.put("warnXbFlowCount", xbFlowCount);

        List<TerminalsFreezeXbView> terminalsFreezeXbViewList = terminalsFreezeXbViewMapper.selectList(new QueryWrapper<TerminalsFreezeXbView>().eq("tenant_id", tenantId)
                .orderByDesc("freeze_time").last(" limit 30 "));
        if (CollUtil.isNotEmpty(terminalsFreezeXbViewList)) {
            terminalsFreezeXbViewList.sort(Comparator.comparing(TerminalsFreezeXbView::getFreezeTime));
            List<String> freezeXbViewFreezeTimeList = terminalsFreezeXbViewList.stream().map(TerminalsFreezeXbView::getFreezeTime).collect(Collectors.toList());
            List<Double> freezeXbViewCblList = terminalsFreezeXbViewList.stream().map(TerminalsFreezeXbView::getCbl).map(BigDecimal::doubleValue).collect(Collectors.toList());
            List<Double> freezeXbViewCumulativeFlowList = terminalsFreezeXbViewList.stream().map(item -> item.getCumulativeFlow() == null ? 0D : item.getCumulativeFlow().doubleValue()).collect(Collectors.toList());
            resultMap.put("trendTimeList", freezeXbViewFreezeTimeList);
            resultMap.put("trendCblList", freezeXbViewCblList);
            resultMap.put("trendFlowList", freezeXbViewCumulativeFlowList);
        } else {
            resultMap.put("trendTimeList", new ArrayList<>());
            resultMap.put("trendCblList", new ArrayList<>());
            resultMap.put("trendFlowList", new ArrayList<>());
        }

//        resultMap.put("countConcentrator", concentratorList.size());

        return resultMap;
    }

    private Integer getWarnCount(List<DmWarn> warnDataList, Integer warnParamType) {
        if (CollUtil.isEmpty(warnDataList)) {
            return 0;
        } else {
            return Math.toIntExact(warnDataList.stream().filter(item -> Objects.equals(item.getWarnParamType(), warnParamType)).count());
        }
    }
}
